import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class NioSocketServer {
    private static final int BUFFER_SIZE = 1024;
    private static final int[] PORT_LIST = new int[]{8001, 8002, 8003, 8004, 8005, 8006, 8007, 8008, 8009, 8010};

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();

        /**
         * 创建多个socket channel，并注册到selector上
         */
        for (int i = 0; i < PORT_LIST.length; i++) {
            int port = PORT_LIST[i];
            ServerSocketChannel listnChannel = ServerSocketChannel.open(); // 打开通道
            listnChannel.socket().bind(new InetSocketAddress("localhost", port));
            listnChannel.configureBlocking(false);
            listnChannel.register(selector, SelectionKey.OP_ACCEPT);
        }

        System.out.println("Server: socket server started...");

        while (true) {
            selector.select();
            Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (key.isValid() && key.isAcceptable()) {
                    // 客户端连接
                    SocketChannel clntChannel = ((ServerSocketChannel) key.channel()).accept();
                    clntChannel.configureBlocking(false);
                    clntChannel.register(key.selector(), SelectionKey.OP_READ);
                }

                if (key.isValid() && key.isReadable()) {
                    // 客户端发送信息，服务器端可读
                    ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
                    SocketChannel clntChan = (SocketChannel) key.channel();
                    while (true) {
                        int readBytes = clntChan.read(byteBuffer);
                        if (readBytes > 0) {
                            System.out.println("Server: data from client = " + new String(byteBuffer.array(), 0, readBytes));
                            byteBuffer.flip();
                            clntChan.write(byteBuffer);
                            break;
                        }
                    }

                    clntChan.close(); // 关闭连接
                }

                if (key.isValid() && key.isWritable()) {
                    // 服务器端可以向客户端发送数据
                    ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
                    byteBuffer.flip();
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    socketChannel.write(byteBuffer);
                    if (byteBuffer.hasRemaining()) {
                        key.interestOps(SelectionKey.OP_READ);
                    }
                    byteBuffer.compact();
                }

                keyIterator.remove();
            }
        }
    }
}
